#include <iostream>
#include <memory>
#include <thread>
#include <chrono>
#include <fstream>
#include "viml/vm.h"
#include "viml/debugger.h"
#include "viml/debug_info.h"
#include "viml/compiler.h"

using namespace viml;

// 简单的调试器回调函数
void debug_callback(const DebugEventInfo& event) {
    switch (event.event) {
        case DebugEvent::BREAKPOINT_HIT:
            std::cout << "\n[调试器] 断点命中！位置: " << event.line << " 行，函数: " << event.function << std::endl;
            break;

        case DebugEvent::STEP_COMPLETE:
            std::cout << "\n[调试器] 单步执行完成，位置: " << event.line << " 行" << std::endl;
            break;

        case DebugEvent::FUNCTION_ENTRY:
            std::cout << "\n[调试器] 进入函数: " << event.function << std::endl;
            break;

        case DebugEvent::FUNCTION_EXIT:
            std::cout << "\n[调试器] 退出函数: " << event.function << std::endl;
            break;

        case DebugEvent::VM_PAUSED:
            std::cout << "\n[调试器] 虚拟机暂停" << std::endl;
            break;

        default:
            break;
    }
}

int main() {
    std::cout << "=== VimL调试器测试程序 ===" << std::endl;

    try {
        // 创建虚拟机和编译器
        auto vm = std::make_shared<VM>();
        auto compiler = std::make_unique<Compiler>();

        // 创建调试器和调试信息
        auto debugger = std::make_shared<Debugger>(vm);
        auto debug_info = std::make_shared<DebugInfo>("example/debug_test.vim");

        // 设置调试器
        vm->set_debugger(debugger);
        vm->set_debug_mode(true);
        debugger->set_debug_info(debug_info);

        // 添加调试事件回调
        debugger->add_event_callback(debug_callback);

        // 编译源代码
        std::cout << "\n正在编译调试测试脚本..." << std::endl;
        std::ifstream file("example/debug_test.vim");
        if (!file.is_open()) {
            std::cerr << "错误：无法打开文件 example/debug_test.vim" << std::endl;
            return 1;
        }

        std::string source((std::istreambuf_iterator<char>(file)),
                        std::istreambuf_iterator<char>());

        auto bytecode = compiler->compile(source, "example/debug_test.vim");
        if (!bytecode) {
            std::cerr << "错误：编译失败" << std::endl;
            return 1;
        }

        std::cout << "编译成功！" << std::endl;
        std::cout << "指令数量: " << bytecode->instruction_count() << std::endl;
        std::cout << "常量数量: " << bytecode->constant_count() << std::endl;

        // 设置调试信息
        debug_info->load_source_file();

        // 关键修复：从字节码中复制行号映射到调试信息
        std::cout << "\n建立行号映射..." << std::endl;
        for (size_t pc = 0; pc < bytecode->instruction_count(); ++pc) {
            int line = bytecode->get_line_number(pc);
            if (line > 0) {
                debug_info->add_line_mapping(line, pc);
                std::cout << "  映射 PC=" << pc << " 到行号 " << line << std::endl;
            }
        }

        // 添加一些测试断点（选择实际可执行的行）
        std::cout << "\n设置测试断点..." << std::endl;
        size_t bp1 = debugger->set_breakpoint(8);   // 在第一个echo语句
        size_t bp2 = debugger->set_breakpoint(17);  // 在算术运算部分
        size_t bp3 = debugger->set_breakpoint(25);  // 在字符串连接部分

        std::cout << "设置断点 " << bp1 << " 在第 8 行" << std::endl;
        std::cout << "设置断点 " << bp2 << " 在第 17 行" << std::endl;
        std::cout << "设置断点 " << bp3 << " 在第 25 行" << std::endl;

        // 显示所有断点
        std::cout << "\n当前断点：" << std::endl;
        auto breakpoints = debugger->get_all_breakpoints();
        for (const auto* bp : breakpoints) {
            std::cout << "  断点 " << bp->id << " 在第 " << bp->location.line << " 行" << std::endl;
        }

        // 启动调试器
        std::cout << "\n启动调试器..." << std::endl;
        debugger->start();

        // 执行脚本
        std::cout << "\n开始执行脚本..." << std::endl;
        std::cout << "===========================" << std::endl;

        auto result = vm->execute(bytecode);

        std::cout << "===========================" << std::endl;
        std::cout << "\n脚本执行完成！" << std::endl;
        std::cout << "执行结果: " << result.to_string() << std::endl;

        // 显示调试统计信息
        std::cout << "\n调试统计信息：" << std::endl;
        auto stats = debugger->get_statistics();
        std::cout << "  断点命中次数: " << stats.breakpoints_hit << std::endl;
        std::cout << "  单步执行次数: " << stats.steps_taken << std::endl;
        std::cout << "  变量监视数量: " << stats.variables_watched << std::endl;
        std::cout << "  事件触发次数: " << stats.events_fired << std::endl;

        // 显示虚拟机统计信息
        std::cout << "\n虚拟机统计信息：" << std::endl;
        auto vm_stats = vm->get_statistics();
        std::cout << "  执行指令数: " << vm_stats.instructions_executed << std::endl;
        std::cout << "  函数调用数: " << vm_stats.function_calls << std::endl;
        std::cout << "  执行时间: " << vm_stats.execution_time << " ms" << std::endl;

    } catch (const std::exception& e) {
        std::cerr << "\n错误: " << e.what() << std::endl;
        return 1;
    }

    std::cout << "\n调试器测试完成！" << std::endl;
    return 0;
}